package com.apobates.forum.nanus.core;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.util.Base64;

/**
 * @see //www.java2s.com/Code/Java/Security/EncryptingaStringwithDES.htm
 * @see //community.oracle.com/thread/1528090
 * @author xiaofanku
 * @since 20200521
 */
public final class NanusDesCryp {
    private final String algorithm = "DESede/CBC/PKCS5Padding"; //"DESede/CBC/NoPadding"
    private IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
    /**
     * 加密工具
     */
    private final Cipher encryptCipher ;
    /**
     * 解密工具
     */
    private final Cipher decryptCipher;
    /**
     *
     * @param secretString 秘钥
     * @throws GeneralSecurityException
     */
    public NanusDesCryp(String secretString) throws GeneralSecurityException {
        byte[] keyBytes = secretString.getBytes();
        int l = keyBytes.length;
        //java.security.InvalidKeyException: Wrong key size
        if (keyBytes.length < 24) { // short key ? .. extend to 24 byte key
            byte[] tmpKey = new byte[24];
            System.arraycopy(keyBytes, 0, tmpKey, 0, l); /*static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);*/
            keyBytes = tmpKey;
        }
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        Cipher eCipher = Cipher.getInstance(algorithm);
        eCipher.init(Cipher.ENCRYPT_MODE, key, iv);
        this.encryptCipher = eCipher;
        //
        Cipher dCipher = Cipher.getInstance(algorithm);
        dCipher.init(Cipher.DECRYPT_MODE, key, iv);
        this.decryptCipher = dCipher;

    }

    private byte[] encrypt(byte[] bytes) throws GeneralSecurityException {
        byte[] utf8String = encryptCipher.doFinal(bytes);
        //
        Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encode(utf8String);
    }

    private byte[] decrypt(byte[] bytes) throws GeneralSecurityException {
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] encryptedTextByte = decoder.decode(bytes);
        //
        return decryptCipher.doFinal(encryptedTextByte);
    }

    /**
     * 加密字符串
     *
     * @param strIn 需加密的字符串
     * @return 加密后的字符串
     * @throws java.io.UnsupportedEncodingException
     * @throws java.security.GeneralSecurityException
     */
    public String encrypt(String strIn) throws UnsupportedEncodingException, GeneralSecurityException{
        byte[] utf8String = strIn.getBytes("UTF8");
        return new String(encrypt(utf8String), "UTF8");
    }

    /**
     * 解密字符串
     *
     * @param strIn 需解密的字符串
     * @return 解密后的字符串
     * @throws java.io.UnsupportedEncodingException
     * @throws java.security.GeneralSecurityException
     */
    public String decrypt(String strIn) throws UnsupportedEncodingException, GeneralSecurityException{
        byte[] utf8String = strIn.getBytes("UTF8");
        return new String(decrypt(utf8String), "UTF8");
    }
}
